#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2025/9/26 13:13
# @Author  : pym
# @File    : draw_L.py
# @Project : python_learn
# @Desc    : 绘制xyz(Linux)

import glob
import os

import numpy as np
import matplotlib
matplotlib.use('Agg')  # 使用非交互式后端
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
# plt.rcParams['axes.unicode_minus'] = False    # 用来正常显示负号

def read_xyz_file(filename):
    """
    读取.xyz文件并返回坐标数据

    参数:
    filename: .xyz文件路径

    返回:
    points: numpy数组，形状为(n, 3)，包含x,y,z坐标
    """
    points = []

    try:
        with open(filename, 'r') as file:
            lines = file.readlines()

            for line in lines:
                # 跳过空行和注释行
                if not line.strip() or line.startswith('#'):
                    continue

                # 分割每行的数据
                data = line.split()

                # 确保至少有3个数值（x,y,z坐标）
                if len(data) >= 3:
                    try:
                        x = float(data[0])
                        y = float(data[1])
                        z = float(data[2])
                        points.append([x, y, z])
                    except ValueError:
                        print(f"警告: 跳过无法解析的行: {line.strip()}")
                        continue

    except FileNotFoundError:
        print(f"错误: 文件 '{filename}' 未找到")
        return None
    except Exception as e:
        print(f"读取文件时出错: {e}")
        return None

    return np.array(points)


def plot_point_cloud(points, title="3D点云图", point_size=1, alpha=0.7,
                     color='blue', elev=30, azim=45, save_path=None, show=False):
    """
    绘制3D点云图

    参数:
    points: 点坐标数组，形状为(n, 3)
    title: 图表标题
    point_size: 点的大小
    alpha: 透明度
    color: 点的颜色
    elev: 仰角
    azim: 方位角
    save_path: 保存图片的路径（可选）
    """
    if points is None or len(points) == 0:
        print("错误: 没有可用的点数据")
        return

    # 创建3D图形
    fig = plt.figure(figsize=(10, 8))
    ax = fig.add_subplot(111, projection='3d')

    # 提取x,y,z坐标
    x = points[:, 0]
    y = points[:, 1]
    z = points[:, 2]

    # 绘制散点图
    scatter = ax.scatter(x, y, z,
                         c=color,
                         s=point_size,
                         alpha=alpha,
                         marker='o')

    # 设置坐标轴标签
    ax.set_xlabel('X坐标')
    ax.set_ylabel('Y坐标')
    ax.set_zlabel('Z坐标')

    # 设置标题
    ax.set_title(title)

    # 设置视角
    ax.view_init(elev=elev, azim=azim)

    # 添加颜色条（如果使用颜色映射）
    if isinstance(color, np.ndarray) or (
            isinstance(color, str) and color not in ['r', 'g', 'b', 'c', 'm', 'y', 'k', 'w']):
        plt.colorbar(scatter, ax=ax, label='数值')

    # 添加网格
    ax.grid(True, alpha=0.3)

    # 等比例缩放坐标轴
    max_range = max([x.max() - x.min(), y.max() - y.min(), z.max() - z.min()]) / 2.0
    mid_x = (x.max() + x.min()) * 0.5
    mid_y = (y.max() + y.min()) * 0.5
    mid_z = (z.max() + z.min()) * 0.5
    ax.set_xlim(mid_x - max_range, mid_x + max_range)
    ax.set_ylim(mid_y - max_range, mid_y + max_range)
    ax.set_zlim(mid_z - max_range, mid_z + max_range)

    plt.tight_layout()

    # 保存图片（如果指定了路径）
    if save_path:
        plt.savefig(save_path, dpi=300, bbox_inches='tight')
        print(f"图片已保存至: {save_path}")

    if show:
        plt.show()
    else:
        plt.close(fig)

    # 打印统计信息
    print(f"点云统计信息:")
    print(f"总点数: {len(points)}")
    print(f"X范围: [{x.min():.4f}, {x.max():.4f}]")
    print(f"Y范围: [{y.min():.4f}, {y.max():.4f}]")
    print(f"Z范围: [{z.min():.4f}, {z.max():.4f}]")


# 主函数
def main():
    # os.makedirs('./pic', exist_ok=True)
    # os.makedirs('./xyz', exist_ok=True)

    xyz_files = glob.glob('./xyz/*.xyz')
    if not xyz_files:
        print("in ./xyz is empty")
        return

    # 循环处理每个文件
    for filename in xyz_files:
        try:
            # 读取点云数据
            points = read_xyz_file(filename)

            if points is not None:
                # 绘制点云图
                plot_point_cloud(points,
                                 title=f"3D点云图 - {filename}",
                                 point_size=20,
                                 alpha=0.8,
                                 color='red',
                                 elev=30,
                                 azim=45,
                                 save_path=f"./pic/{filename}_point_cloud.png")


        except Exception as e:
            print(f"{filename}: {e}")

if __name__ == "__main__":
    main()
